//
//  main.m
//  07_code  内存管理
//
//  Created by dllo on 16/7/12.
//  Copyright © 2016年 yh. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Man.h"

int main(int argc, const char * argv[]) {
    // 内存问题
    // 1. 内存溢出 没存用尽 导致crash
    // 2. 野指针 指针指向被释放的地方 过度释放
    // 内存方式
    // 垃圾回收机制 只有mac有
    // MRC 手动管理引用计数
    // ARC 自动管理引用计数 ARC基于MRC
    
    // 看到 retain alloc copy 引用计数加1 需要进行内存管理
    NSObject *objc = [[NSObject alloc] init];
    [objc retain];
    // 需要两次释放
    [objc release];
    [objc release];
    // 内存管理 引用计数 (计数器)
    // release autorelease 会对引用计数减1
    // 当对象的引用计数为0时 系统会调用相应的dealloc方法
    
    // 对对象操作完成后 再进行释放
    Man *man = [[Man alloc] init];
    NSLog(@"%ld", man.retainCount);
    [man release];
    
//    NSLog(@"%ld", man.retainCount);
//    [man sayGoodBye];
//    [man sayHello];

    // 集合类型 会对对象进行引用计数加1
    // addObject 对数组对象引用计数加1
    // removeObject 对 对象引用计数 减1
    // 将man添加到数组中 man的引用计数会加1
//    NSMutableArray *array = [NSMutableArray arrayWithObjects:man, nil];
//    NSLog(@"%ld", man.retainCount);
//    [array removeAllObjects];
//    NSLog(@"man: %ld", man.retainCount);

    // 2. ARC
    // (语义特性)
    // strong(强引用 引用计数加1) weak(应用于简单对象类型 弱引用 对象被释放时 对象会自动置空) retain(强引用 引用计数加1) copy(吧对象拷贝一份 原来的引用计数不变 新对象的引用计数加1) assign(应用于简单数据类型 不会产生引用计数)
    
    // 协议
    // 1. 声明协议
    // 2. 签订协议
    // 3. 实现协议方法
    
    // 要实现对象的拷贝
    // 1. 签订协议NSCopying (一般字符串用copy 安全)
    // 2. 实现协议方法copyWithZone
    Man *newMan = [man copy]; // 拷贝后 地址不同是两个完全不同的对象
    NSLog(@"newMan: %@ - oldMan: %@", newMan, man);
    
    // KVC Key - Value - Coding 键值编码 间接取值或者赋值
    //    newMan setValue:<#(nullable id)#> forKey:<#(nonnull NSString *)#>]
    newMan.name = @"zhaohao";
    newMan.sexual = @"nan";
    
    id name = [newMan valueForKey:@"sexual"];
    NSLog(@"%@", name);
    
    [newMan setValue:@"坏蛋" forKey:@"name"];
    NSLog(@"%@", newMan.name);
    // 只要是NSObject 的子类就可以用这些方法
    // valueForKey
    // valueForKeyPath
    // setValue: forKey
    //  setValue: forKeyPath
    
    
    Man *gayMan = [[Man alloc] init];
    gayMan.gayBoy = newMan;
    id boyName = [gayMan valueForKeyPath:@"gayBoy.name"];
    NSLog(@"boyName: %@", boyName);
    [gayMan release];
    [gayMan setValue:@"haobao" forKeyPath:@"gayBoy.name"];
    NSLog(@"%@", gayMan.gayBoy.name);
    
    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
    [dic setValue:@"赵好" forKey:@"name"];
    NSLog(@"%@", dic);
    
    NSDictionary *dic1 = [[NSDictionary alloc] initWithObjectsAndKeys:@"1234567", @"id", @"顶顶顶顶顶顶顶顶顶", @"description", nil];
    Man *dicMan = [[Man alloc] init];
    [dicMan setValuesForKeysWithDictionary:dic1];
    
    // 在ARC工程下使用MRC的文件(三方) -fno-objc-arc
    // 在MRC工程下使用ARC的文件         -fobjc-arc
    // 需要加在 build phases下的编译source下
    
    
    
    
    return 0;
}










